import json
import random
from datetime import timedelta

from django.core.cache import cache
from django.utils import timezone
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenObtainSerializer
from rest_framework_simplejwt.tokens import AccessToken
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.decorators import action

from application import dispatch
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.request_util import save_login_log
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.validator import CustomValidationError
from dvadmin.utils.viewset import CustomModelViewSet
from dvadmin_third.models import ThirdUsers
from dvadmin_uniapp.alibabacloud import AliBabaCloudSample


class UniAppWxLoginSerializer(TokenObtainSerializer):
    """
    微信登录的序列化器:
    """
    captcha = serializers.CharField(
        max_length=6, required=False, allow_null=True, allow_blank=True
    )

    class Meta:
        model = Users
        fields = "__all__"
        read_only_fields = ["id"]

    default_error_messages = {"no_active_account": "code无效"}

    @classmethod
    def get_token(cls, user):
        Refresh = AccessToken
        Refresh.lifetime = timedelta(days=15)
        return Refresh.for_user(user)

    def validate(self, attrs):
        app_id = self.initial_data.get("app_id", None)
        if not app_id:
            raise CustomValidationError("app_id不能为空")
        data = super().validate(attrs)
        refresh = self.get_token(self.user)
        data['access'] = str(refresh)
        self.user.last_login = timezone.now()
        self.user.save()
        request = self.context.get("request")
        request.user = self.user
        # 记录登录日志
        save_login_log(request=request)
        return {"code": 2000, "msg": "请求成功", "data": {"token": data.get('access')}}


class UniAppPhoneLoginSerializer(TokenObtainPairSerializer):
    """
    手机号登录的序列化器:
    """

    class Meta:
        model = Users
        fields = "__all__"
        read_only_fields = ["id"]

    default_error_messages = {"no_active_account": "验证码无效"}

    def validate(self, attrs):
        app_id = self.initial_data.get("app_id", None)
        if not app_id:
            raise CustomValidationError("app_id不能为空")
        login_type = self.initial_data.get("login_type", None)
        if login_type != 'phone':
            raise CustomValidationError("登录类型错误")

        data = super().validate(attrs)
        request = self.context.get("request")
        request.user = self.user
        # 记录登录日志
        save_login_log(request=request)
        return {"code": 2000, "msg": "请求成功", "data": {"token": data.get('access')}}


class UniAppWxLoginView(TokenObtainPairView):
    """
    微信登录接口
    """

    serializer_class = UniAppWxLoginSerializer
    permission_classes = []


class UniAppPhoneLoginView(TokenObtainPairView):
    """
    手机号登录接口
    """

    serializer_class = UniAppPhoneLoginSerializer
    permission_classes = []


class UniAppSendSmsView(APIView):
    """
    登录发送验证码
    """
    permission_classes = []
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        """
        发送验证码
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        phone = request.data.get('phone')
        # 1.校验手机号是否正确
        if len(phone) != 11:
            return ErrorResponse(msg=f"请输入正确的手机号!")
        is_send_sms = cache.get(f"uniapp_send_sms_{phone}")
        if is_send_sms:
            return ErrorResponse(msg=f"60秒内只能发送一次!")
        sample = AliBabaCloudSample()
        # 判断是否是微信审核状态，且手机号为固定手机号
        # 审核手机号：13111111111
        if phone in ['13111111111']:
            code = 999999
            cache.set(f"uniapp_send_sms_{phone}", code, 60)
            cache.set(f"uniapp_code_{phone}", code, 300)
            return DetailResponse(msg=f"发送成功!")
        else:
            code = random.randint(100000, 999999)
            if sample.send_sms(sign_name=dispatch.get_system_config_values("uniapp.sms_sign_name") or '巨梦科技',
                               template_code=dispatch.get_system_config_values("uniapp.sms_template_code") or 'SMS_xxx',
                               phone_numbers=phone,
                               template_param='{"code":"' + str(code) + '"}'):
                cache.set(f"uniapp_send_sms_{phone}", code, 60)
                cache.set(f"uniapp_code_{phone}", code, 300)
                return DetailResponse(msg=f"发送成功!")
        return ErrorResponse(msg=f"发送失败，请联系管理员!")


class UniAppUserInfoSerializer(CustomModelSerializer):
    """
    用户信息的序列化器:
    """
    dept_name = serializers.CharField(read_only=True, source='dept.name', default='')
    role = serializers.CharField(read_only=True, source='get_user_type_display', default='')

    def to_representation(self, instance: Users):
        Users.objects.values('user_type')
        data = super().to_representation(instance)
        data = json.loads(json.dumps(data))
        third_users_obj = ThirdUsers.objects.filter(user=self.request.user).first()
        if third_users_obj:
            data["province"] = third_users_obj.province
            data["city"] = third_users_obj.city
            data["is_we_chat"] = third_users_obj.id
        return data

    class Meta:
        model = Users
        fields = ["id", "username", "mobile", "avatar", "name", "role", "gender", "user_type", "dept_name"]
        read_only_fields = ["id"]


class UniAppUserInfoView(CustomModelViewSet):
    """
    用户信息接口
    """

    serializer_class = UniAppUserInfoSerializer
    permission_classes = []
    queryset = Users.objects.all()
    extra_filter_backends = []

    @action(methods=["GET"], detail=False, permission_classes=[])
    def get_user_info(self, request, *args, **kwargs):
        """
        UniApp小程序获取用户信息
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        serializer = self.get_serializer(self.request.user)
        return DetailResponse(data=serializer.data, msg="获取成功")

    @action(methods=["POST"], detail=False, permission_classes=[])
    def save_user_info(self, request, *args, **kwargs):
        """
        保存用户信息
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        self.request.user.name = request.data.get('name', '')
        self.request.user.avatar = request.data.get('avatar', '')
        self.request.user.gender = request.data.get('sex', 0)
        self.request.user.save()
        return DetailResponse(msg=f"保存成功")
